<?php

/**
 * @author      Nguyen Duc Thuan <me@ndthuan.com>
 * @copyright   Copyright (c) 2009 Nguyen Duc Thuan <me@ndthuan.com>
 * @version     $Id: Request.php 12 2009-11-03 03:17:46Z thuan.nguyen $
 */

final class Fete_Request
{
    private $_action        = 'home';
    private $_routes        = array();
    private $_currentRoute  = 'default';
    private $_params        = array();
    private $_clientIp      = null;

    /**
     *
     * @var Fete_Request
     */
    static private $_instance = null;

    /**
     *
     * Get instance of this class
     * @return Fete_Request
     */
    static public function getInstance()
    {
        if (null === self::$_instance) {
            self::$_instance = new self();
        }

        return self::$_instance;
    }

    /**
     *
     * Initialize requets
     * @return Fete_Request
     */
    public function &init()
    {        
        $requestUri = preg_replace('#^' . Fete_Front::getInstance()->getBaseUrl() . '/#i', '', $_SERVER['REQUEST_URI']);

        if ('' !== $requestUri) {
            $questionMarkPos = strpos($requestUri, '?');

            if (false === $questionMarkPos) {
                $query = $requestUri;
            } else {
                $query = substr($requestUri, 0, $questionMarkPos);
            }

            if ('' !== $query) {
                foreach ($this->_routes as $name => &$route)
                {
                    if ($route->match($query)) {
                        $this->_currentRoute = $name;
                        $params = $route->getParams();
                        $this->setAction($params['action']);
                        unset($params['action']);
                        $this->setParams($params);
                        return $this;
                    }
                }

                $segments = explode('/', $query);

                $this->_action = $segments[0];

                $maxIndex = count($segments) - 1;

                for ($counter = 1; $counter <= $maxIndex; $counter += 2)
                {
                    if (!isset($segments[$counter])) {
                        break;
                    }

                    $nextCounter = $counter + 1;
                    $key = $segments[$counter];
                    if (isset($segments[$nextCounter])) {
                        $value = $segments[$nextCounter];
                    } else {
                        $value = null;
                    }
                    $this->_params[$key] = $value;
                }
            }
        }

        return $this;
    }

    /**
     * @param $appName
     * @return Fete_Request
     */
    public function &setApp($appName)
    {
        $this->_app = $appName;

        return $this;
    }

    /**
     *
     * Get current app name
     * @return string
     */
    public function getApp()
    {
        return $this->_app;
    }

    /**
     *
     * Set controller
     * @param $controllerName
     * @return Fete_Request
     */
    public function &setController($controllerName)
    {
        $this->_controller = $controllerName;

        return $this;
    }

    public function getController()
    {
        return $this->_controller;
    }

    /**
     * @param $action
     * @return Fete_Request
     */
    public function &setAction($action)
    {
        $this->_action = $action;

        return $this;
    }

    public function getAction()
    {
        return $this->_action;
    }

    /**
     * @param $name
     * @param $value
     * @return Fete_Request
     */
    public function &setParams($name, $value = null)
    {
        if (is_array($name)) {
            foreach ($name as $key => $value)
            {
                $this->_params[$key] = $value;
            }
        } else {
            $this->_params[$name] = $value;
        }

        return $this;
    }

    /**
     * @param $param
     * @return string
     */
    public function getParam($param)
    {
        if (isset($this->_params[$param])) {
            return $this->_params[$param];
        } elseif (isset($_REQUEST[$param])) {
            return $_REQUEST[$param];
        }

        return null;
    }

    public function getAllParams()
    {
        return $this->_params;
    }

    /**
     * @param $name
     * @param Fete_Route $route
     * @return Fete_Request
     */
    public function &addRoute($name, Fete_Route $route)
    {
        $this->_routes[$name] = $route;

        return $this;
    }

    /**
     * @param $name
     * @return Fete_Route
     */
    public function getRouteInstance($name)
    {
        if (isset($this->_routes[$name])) {
            return $this->_routes[$name];
        }

        return null;
    }

    /**
     *
     * Get current route
     * @return Fete_Route
     */
    public function getCurrentRouteName()
    {
        return $this->_currentRoute;
    }

    /**
     *
     * Get current route instance
     * @return Fete_Route
     */
    public function &getCurrentRouteInstance()
    {
        return $this->_routes[$this->_currentRoute];
    }

    /**
     *
     * @return bool
     */
    public function isPost()
    {
        return 'POST' === $_SERVER['REQUEST_METHOD'];
    }

    /**
     *
     * @return string IP address of request client
     */
    public function getClientIp()
    {
        if (null === $this->_clientIp) {
            if (isset($_SERVER['HTTP_CLIENT_IP'])) {
                $ip = $_SERVER['HTTP_CLIENT_IP'];
            } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
                $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
            } else {
                $ip = $_SERVER['REMOTE_ADDR'];
            }
            $this->_clientIp = $ip;
        }
        return $this->_clientIp;
    }

    private function __construct() {}
    private function __clone() {}
}